/*
*
* 版权所有 Copyleft(c) 2005
* 刘炯个人工作室 Sharp-Mark Personal Studio
*
* 允许自由使用，复制，修改，传播和贩卖此源程序及其文档，而不必支付任何费用。
* 以上的版权信息必须出现在每一份复制品中。同时这份版权信息和许可声明
* 也必须出现在支持文档中。刘炯个人工作室不对此软件适于那种具体
* 用途做出任何阐述。此代码只作为代码本身提供对其品质不做任何保证。
*
*/

// ChildView.cpp : CChildView 类的实现
//

#include "stdafx.h"
#include "PolyFill.h"
#include "ChildView.h"
#include ".\childview.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#endif


// CChildView

CChildView::CChildView()
{
}

CChildView::~CChildView()
{
}


BEGIN_MESSAGE_MAP(CChildView, CWnd)
	ON_WM_PAINT()
END_MESSAGE_MAP()



// CChildView 消息处理程序

BOOL CChildView::PreCreateWindow(CREATESTRUCT& cs) 
{
	if (!CWnd::PreCreateWindow(cs))
		return FALSE;

	cs.dwExStyle |= WS_EX_CLIENTEDGE;
	cs.style &= ~WS_BORDER;
	cs.lpszClass = AfxRegisterWndClass(CS_HREDRAW|CS_VREDRAW|CS_DBLCLKS, 
		::LoadCursor(NULL, IDC_ARROW), reinterpret_cast<HBRUSH>(COLOR_WINDOW+1), NULL);

	return TRUE;
}

void CChildView::OnPaint() 
{
	CPaintDC dc(this); // 用于绘制的设备上下文

	CRect rect;
	GetClientRect(rect);

	POINT points[7];
	points[0].x = 200;
	points[0].y = 40;

	points[1].x = 400;
	points[1].y = 200;

	points[2].x = 300;
	points[2].y = 200;

	points[3].x = 300;
	points[3].y = 400;

	points[4].x = 100;
	points[4].y = 400;

	points[5].x = 100;
	points[5].y = 200;

	points[6].x = 1;
	points[6].y = 200;

	CEdge edges[7];
	dc.MoveTo(points[0]);
	edges[0] = CEdge(points[0], points[1]);
	dc.LineTo(points[1]);
	edges[1] = CEdge(points[1], points[2]);
	dc.LineTo(points[2]);
	edges[2] = CEdge(points[2], points[3]);
	dc.LineTo(points[3]);
	edges[3] = CEdge(points[3], points[4]);
	dc.LineTo(points[4]);
	edges[4] = CEdge(points[4], points[5]);
	dc.LineTo(points[5]);
	edges[5] = CEdge(points[5], points[6]);
	dc.LineTo(points[6]);
	edges[6] = CEdge(points[6], points[0]);
	dc.LineTo(points[0]);

	CPolygon polygon(edges, 7);
	PolyFillEdgeScan(polygon, RGB(200, 100, 100), dc, rect);
}

void CChildView::PolyFillEdgeScan(CPolygon& polygon, COLORREF color, CPaintDC& dc, CRect& rect)
{
	// 确定上下边界
	int bottom = rect.Height();
	int top = 0;

	for(int i = 0; i < polygon.Num; i++)
	{
		if( bottom >= polygon.Edges[i].yMin )
		{
			bottom = polygon.Edges[i].yMin;
		}

		if( top <= polygon.Edges[i].yMax )
		{
			top = polygon.Edges[i].yMax;
		}
	}


	CNewEdgeTable net(top - bottom + 1);			// 生成NewEdgeTable.

	// 扫描各条边
	int b = bottom;
	for(vector< list<CEdgeNode> * >::iterator vp = net.Links.begin(); vp != net.Links.end(); vp++)
	{
		for(int j = 0; j < polygon.Num; j++)
		{
			if(polygon.Edges[j].yMin == b)
			{
				(**vp).push_back(CEdgeNode((float)polygon.Edges[j].xMin,
					polygon.Edges[j].dx, polygon.Edges[j].yMax));
			}
		}
		b++;
	}

	CActiveEdgeTable aet;

	for(int i = 0; i <= top - bottom; i++ )
	{
		aet.InsertNodes(net.Links[i]);

		for(list< CEdgeNode >::iterator p = aet.Link.begin(); p != aet.Link.end(); ++p)
		{
			CEdgeNode& start = (*p);
			p++;
			if(p == aet.Link.end()) break;
			CEdgeNode& end = (*p);

			int y1, y2;
			int y = i + bottom;
			if(start.X == end.X)
			{
				y1 = polygon.GetEdgePointY((int)start.X, y, start.Dx);
				y2 = polygon.GetEdgePointY((int)end.X, y, end.Dx);

				if(start.Dx == 0 || end.Dx == 0)
				{
					int nextX1 = polygon.GetEdgePointX((int)start.X, y, 0);
					int nextX2 = polygon.GetEdgePointX((int)end.X, y, 0);
					if((++p) != aet.Link.end() && nextX1 != (*p).X && nextX2 != (*p).X)
					{
						for(int n = start.X + 1; n < end.X; n++)
						{
							dc.SetPixelV(n, i + bottom, color);
						}
					}
					p--;
										
				}
				else if(y1 > y && y2 > y)
				{
					for(int n = start.X + 1; n < end.X; n++)
					{
						dc.SetPixelV(n, i + bottom, color);
					}
				}
				else if(y1 > y || y2 > y)
				{
					p--;
				}
				else
				{
					continue;
				}
			}
			else
			{
				if(start.Dx == 0 || end.Dx == 0)
				{
					int nextX = polygon.GetEdgePointX((int)start.X, y, 0);

					if(end.X != nextX)
					{
						for(int n = start.X + 1; n < end.X; n++)
						{
							dc.SetPixelV(n, i + bottom, color);
						}
					}
					
					continue;
				}
				else
				{
					for(int n = int(start.X + 0.5) + 1; n < end.X; n++)
					{
						dc.SetPixelV(n, i + bottom, color);
					}
				}
			}
		}

		for(list<CEdgeNode>::iterator p = aet.Link.begin(); p != aet.Link.end();)
		{
			if ((*p).Y == (i + bottom))
			{
				list<CEdgeNode>::iterator delp = p;
				p++;
				aet.Link.erase(delp);
			}
			else
			{
				(*p).X += (*p).Dx;
				p++;
			}

		}

		aet.Link.sort(CompareEdge());
	}
}